package com.zh.flowable.domain.flow.listener;

import com.zh.flowable.domain.AuditAction;
import com.zh.flowable.domain.AuditStatus;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * @author
 * @date 2025/8/29
 */
@Slf4j
@Component
public class ProcessEndCallback implements ExecutionListener {
    private final RestTemplate restTemplate;
    private final RuntimeService runtimeService;

    public ProcessEndCallback(RestTemplate restTemplate, RuntimeService runtimeService) {
        this.restTemplate = restTemplate;
        this.runtimeService = runtimeService;
    }

    @Override
    public void notify(DelegateExecution execution) {
        String processDefinitionId = execution.getProcessDefinitionId();
        String instanceId = execution.getProcessInstanceId();

        String[] split = processDefinitionId.split(":");
        String processKey = split[0];

        var auditAction = (String) execution.getVariable("auditAction");

        log.info("流程结束回调 触发中... - 流程定义Key: {}, 流程实例ID: {}", processKey, instanceId);

        if (AuditAction.Approve.name().equals(auditAction)) {
            //审批通过
            runtimeService.updateBusinessStatus(instanceId, String.valueOf(AuditStatus.APPROVED.getCode()));

        } else if (AuditAction.Revert.name().equals(auditAction)) {
            //审批被驳回
            runtimeService.updateBusinessStatus(instanceId, String.valueOf(AuditStatus.REVERTED.getCode()));

        } else if (AuditAction.Disapprove.name().equals(auditAction)) {
            //审批不通过
            runtimeService.updateBusinessStatus(instanceId, String.valueOf(AuditStatus.DISAPPROVED.getCode()));
        }

        String flowNo = execution.getProcessInstanceBusinessKey();
        String status = execution.getProcessInstanceBusinessStatus();
        String tenantId = execution.getTenantId();

        CompletableFuture.runAsync(() -> {
            this.callback(processKey, flowNo, status, tenantId);
        }).exceptionally(ex -> {
            log.error("流程结束回调 失败 - 流程定义Key: {}, 流程实例ID: {} . 异常信息: {}", processKey, instanceId, ex.getMessage());
            return null;
        });
    }

    @Value("${flowable-client-callback}")
    private List<String> callbackUrls;

    static final AtomicInteger index = new AtomicInteger(0);

    //回调客户端接口
    public void callback(String processKey, String flowNo, String status, String tenantId) {
        int size = callbackUrls.size();
        if (size == 0) {
            log.warn("无法回调，flowable-client-callback is empty");
            return;
        }

        Map<String, String> params = Map.of("processKey", processKey != null ? processKey : "", "flowNo", flowNo != null ? flowNo : "", "status", status != null ? status : "", "tenantId", tenantId != null ? tenantId : "");

        String url = callbackUrls.get(0);

        if (size > 1) { //轮询回调
            url = callbackUrls.get(index.getAndSet((index.get() + 1) % size));
        }

        log.info(">>> ClientFlow request url: {}, params: {}", url, params);
        Map<?, ?> response = restTemplate.postForObject(url, params, Map.class);
        log.info("<<< ClientFlow response = {}", response);
    }
}
